import Konva from 'konva'
import { formatImgWH, formatNumber, isJSON } from 'src/utils/utils'
import { amrPanel } from 'src/views/MapCore/MapGlobal/utils/KonvaEvent.js'
import { connectingLineByStartAMREnd, warnBorderColor } from 'src/views/MapCore/MapGlobal/utils/MouseEvent'
import { formatAMRImage } from 'src/views/MapCore/MapGlobal/utils/utils.js'

let AMR
const IMG_SIZE = 2.2, FONT_SIZE = 0.25, FONT_SCALE = 1, lastMoveInfo = {}

const declarePoint = () => {
  AMR = new Konva.Image({ image: null, width: IMG_SIZE, height: IMG_SIZE })
  AMR.cache()
}

export const getModelImg = async (canvas, modelInfo = {}, name = '') => {
  const IMGSrc = toggleAMRImg('/', modelInfo.amrStatus, modelInfo.agvTypeCode)
  return new Promise(resolve => {
    const image = new Image()
    image.src = IMGSrc
    image.onload = () => {
      const { width, height } = formatImgWH(image, IMG_SIZE)
      const { posX: x, posY: y, amrAngle: rotation } = modelInfo
      if (!AMR) declarePoint()
      const amrIMG = AMR.clone({ image, width, height }), { agvBrandCode: brandCode, agvCode } = modelInfo
      const amrCodeText = new Konva.Text({
        text: agvCode, fontSize: FONT_SIZE, fill: 'rgba(255,183,77,0.7)', fontStyle: 'bold', listening: false
      })
      const agvBrandCode = new Konva.Text({
        text: brandCode, fontSize: FONT_SIZE, fill: 'rgba(255,183,77,0.85)', fontStyle: 'bold', listening: false
      })
      const offsetX = (width - amrCodeText.width() * FONT_SCALE) * -0.5 / FONT_SCALE
      const offsetY = amrCodeText.height() * 0.95 - height * 0.25
      amrCodeText.offset({ x: offsetX, y: offsetY })
      const brandOX = (width - agvBrandCode.width() * FONT_SCALE) * -0.5 / FONT_SCALE
      const brandOY = -height * 0.76
      agvBrandCode.offset({ x: brandOX, y: brandOY })
      const group = new Konva.Group({
        name, width, height, x, y, offsetX: width / 2, offsetY: height / 2, rotation, scaleY: -1
      })
      group.on('mouseout', () => (canvas.container().style.cursor = 'move'))
      group.on('mouseenter mousemove', () => (canvas.container().style.cursor = 'pointer'))
      group.on('dblclick', e => {
        e.cancelBubble = true
        amrPanel.value = { agvCode, visible: true, evt: e.evt, amrInfo: modelInfo }
      })
      group.add(amrIMG, amrCodeText, agvBrandCode)
      resolve(group)
    }
  })
}

const getLayer = canvas => {
  if (!canvas) return
  const layer = canvas.findOne('.AMRs')
  if (layer) return layer
  const MonitorLayer = new Konva.Group({ name: 'AMRs' })
  canvas.findOne('.shapeLayer').add(MonitorLayer)
  MonitorLayer.moveToTop()
  return MonitorLayer
}

const toggleAMRImg = (amrSrc = '/', amrStatus = '', amrType = '') => {
  if (!amrSrc || !amrStatus) return
  const currentSrc = formatAMRImage(amrStatus, amrType)
  return amrSrc === currentSrc ? '' : currentSrc
}
const done = (AMRShape, amrStatus, amrType) => {
  if (!AMRShape || !AMRShape.getLayer()) return
  const AMRImg = AMRShape.findOne('Image').image()
  if (!AMRImg) return
  const src = toggleAMRImg(AMRImg.src, amrStatus, amrType)
  if (src) AMRImg.src = src
}
// const modelTween = (moveInfo, model, TIME) => {
//   if (!model) return
//   moveInfo.amrAngle = Math.round(Number(moveInfo.amrAngle) || 0) + 90
//   const { amrAngle: rotation, posX: x, posY: y } = moveInfo
//   if (rotation === model.rotation() && x === model.x() && y === model.y()) return
//   const tween = new Konva.Tween({
//     node: model, duration: TIME, x, y, rotation, onFinish: () => tween.destroy()
//   })
//   tween.play()
// }
const getDiffR = (moveInfo, model) => {
  if (!model) return 0
  const { amrAngle: rotation } = moveInfo
  const lastR = formatNumber(model.rotation())
  let diffR = formatNumber(rotation - lastR)
  if (diffR > 180) diffR -= 360
  else if (diffR < -180) diffR += 360
  return formatNumber(diffR)
}
const amrAnimation = (canvas, moveInfo, model, TIME) => {
  if (!model) return
  const { agvTypeCode, amrAngle, agvCode, amrStatus, posX: x, posY: y } = moveInfo
  const { amrAngle: LA, posX: LX, posY: LY } = lastMoveInfo[agvCode] || {}
  const { x: lastX = 0, y: lastY = 0, rotation: lastR } = model.getAttrs()
  if (LA === amrAngle && LX === x && LY === y) {
    if (lastX !== x || lastY !== y || amrAngle !== lastR) model.setAttrs({ x, y, rotation: amrAngle })
    return done(model, amrStatus, agvTypeCode)
  }
  if (agvCode === amrPanel.value.agvCode && amrPanel.value.visible) connectingLineByStartAMREnd(canvas, moveInfo)
  lastMoveInfo[agvCode] = { amrAngle, amrStatus, posX: x, posY: y }
  const diffX = formatNumber(x - lastX), diffY = formatNumber(y - lastY), diffR = getDiffR(moveInfo, model)
  const timestamp = TIME * 1000
  let anim = new Konva.Animation(frame => {
    const { timeDiff, time } = frame
    if (time >= timestamp) {
      anim && anim.stop()
      anim = null
      done(model, amrStatus, agvTypeCode)
      return
    }
    model.move({ x: diffX * timeDiff / timestamp, y: diffY * timeDiff / timestamp })
    model.rotate(diffR * timeDiff / timestamp)
    if (canvas.findOne('.selectedShapes').findOne(el => el.getAttr('code') === agvCode)) {
      const { x: posX, y: posY } = model.position()
      connectingLineByStartAMREnd(canvas, { ...moveInfo, posX, posY })
    }
  }, model && model.getLayer())
  anim && anim.start()
}

export const AGVMonitor = async (canvas, modelMap = {}, moveModelInfo = {}, TIME = 1) => {
  const key = modelMap.agvCode, AMRShape = moveModelInfo[key]
  if (modelMap[key] === '1') {
    delete moveModelInfo[key]
    AMRShape && AMRShape.remove()
    key === amrPanel.value.agvCode && (amrPanel.value = { visible: false })
    return
  }
  modelMap.posX = formatNumber(Number(modelMap.posX) / 1000)
  modelMap.posY = formatNumber(Number(modelMap.posY) / 1000)
  modelMap.amrStatus = (modelMap.statusClassNumberCode || '').toUpperCase()
  modelMap.amrAngle = formatNumber(Number(modelMap.agvAngle || 0) - 90)
  if (key === amrPanel.value.agvCode && amrPanel.value.visible) amrPanel.value.amrInfo = modelMap
  if (!AMRShape) {
    const layer = getLayer(canvas)
    if (!layer) return
    moveModelInfo[key] = await getModelImg(canvas, modelMap, key)
    layer.add(moveModelInfo[key])
    return
  }
  amrAnimation(canvas, modelMap, AMRShape, TIME)
  // modelTween(modelMap, AMRShape, TIME)
}

export const areaMonitor = async (canvas, resMsg = {}, areas) => {
  if (!canvas) return
  // 这里有可能拿到的数据格式是Uint8Array格式，所以可以直接用toString转成字符串
  const { areaInfo = {}, isWarn = '1', ruleInfo = {} } = resMsg
  const area = canvas.findOne('.areas').findOne(el => el.getAttr('areaCode') === areaInfo.areaCode)
  if (!area) return
  const index = areas.findIndex(el => el.areaCode === areaInfo.areaCode)
  areaInfo.ruleInfo = ruleInfo
  const text = canvas.findOne('.texts').findOne(el => el.getAttr('uid') === area.getAttr('uid'))
  if (isWarn === '1') {
    text && text.fill('red')
    area.fill('#FF4D4F4D')
    area.stroke(warnBorderColor)
    if (index === -1) areas.push(areaInfo) && playAudio()
  } else {
    const css = areaInfo.css2 && isJSON(areaInfo.css2) ? JSON.parse(areaInfo.css2) : {}
    text && text.fill(text.getAttr('textColor'))
    area.fill(css.fill)
    area.stroke(css.stroke)
    if (index > -1) areas.splice(index, 1)
  }
}
const SpeakInfo = {}
export const playAudio = () => {
  if (!SpeakInfo.audio) SpeakInfo.audio = new Audio('./static/Audio/Alarm.mp3')
  SpeakInfo.audio.play().then(() => {})
}
export const stopAudio = () => SpeakInfo.audio && SpeakInfo.audio.pause()